<template>
  <div
    :class="['editor-box', self_disabled ? 'editor-disabled' : '', 'h-100vh w-1/1']"
    style="background-color: var(--el-color-info-light-8)"
  >
    <div class="h-50px text-14px bg-[var(--el-bg-color)]">
      <div class="flex justify-center flex-col h-1/1">
        <div class="flex justify-center flex-row">
          <div class="relative">
            <span class="px-10px py-5px mx-5px bg-[#000] bg-opacity-[0.03] cursor-pointer" @click="customBrowseAndUpload('image')"
              >图片</span
            >
            <span class="px-10px py-5px mx-5px bg-[#000] bg-opacity-[0.03] cursor-pointer" @click="customBrowseAndUpload('video')"
              >视频</span
            >
          </div>
          <div class="ml-40px" v-if="isShowCard">
            <span class="px-10px py-5px mx-5px bg-[#000] bg-opacity-[0.03] cursor-pointer" @click="chooseLouPan">楼盘卡片</span>
          </div>
          <div class="ml-40px" v-if="isSubmit">
            <span
              class="px-10px py-5px mx-5px bg-[var(--el-color-primary)] text-[var(--el-color-white)] cursor-pointer"
              @click="submit"
              >提交</span
            >
          </div>
        </div>
      </div>
    </div>
    <div class="max-h-40px">
      <Toolbar class="editor-toolbar" :editor="editorRef" :default-config="toolbarConfig" :mode="mode" v-if="!hideToolBar" />
    </div>

    <div class="h-[calc(100%-90px)] relative overflow-y-auto relative">
      <div
        class="w-750px mt-30px mx-auto mb-150px shadow-current pt-20px px-50px pb-50px"
        style="background-color: var(--el-bg-color)"
      >
        <div class="py-20px px-0 relative">
          <el-input
            type="textarea"
            placeholder="请输入标题"
            v-model="baseInfo.title"
            class="text-24px outline-none border-[0px] w-1/1 leading-1 whitespace-pre-line pr-98px"
            :max="64"
            :autosize="true"
            resize="none"
          />
          <div class="absolute right-0 top-[50%] transform translate-y-[-50%]">
            <span :class="baseInfo.title.length > 64 ? 'text-red-500' : 'text-black'">{{ baseInfo.title.length }} / 64</span>
          </div>
        </div>
        <div class="pt-10px px-0 relative" v-if="hasAuthor">
          <el-input
            type="text"
            placeholder="请输入作者"
            v-model="baseInfo.author"
            class="text-15px outline-none border-[0px] w-1/1 leading-1 pr-80px"
          />
          <div class="absolute right-0 top-[50%] transform translate-y-[-50%]">
            <span :class="baseInfo.author!.length > 8 ? 'text-red-500' : 'text-black'">{{ baseInfo.author!.length }} / 8</span>
          </div>
        </div>
        <Editor
          class="editor-content mt-20px"
          :mode="mode"
          :style="{ minHeight }"
          v-model="valueHtml"
          :default-config="editorConfig"
          @on-created="handleCreated"
          @on-blur="handleBlur"
        />
      </div>
    </div>
    <SucaiPopup ref="sucaiRef" @confirm="getUrl" :maxSelect="1" fileType="image"></SucaiPopup>
    <LouPanCard ref="louRef" @card="chooseCard"></LouPanCard>
  </div>
</template>

<script setup lang="ts" name="WangEditor">
import { nextTick, computed, inject, shallowRef, onBeforeUnmount, ref } from "vue";
import { IToolbarConfig, IEditorConfig } from "@wangeditor/editor";
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import "@wangeditor/editor/dist/css/style.css";
import { ElMessage, formContextKey, formItemContextKey } from "element-plus";
import SucaiPopup from "@/components/UploadCool/index.vue";
import LouPanCard from "@/components/loupanCard/index.vue";

const louRef = ref<InstanceType<typeof LouPanCard> | null>();

const chooseLouPan = () => {
  louRef.value?.acceptParams();
};

const chooseCard = (p: any) => {
  console.log(p);
  const html =
    editorRef.value.getHtml() +
    `<p><span style="color:#fff;background-color:rgba(0,0,0,0.5)"><u>%${p.name}[id:${p.id}]%(楼盘卡片，请勿修改)</u></span></p>`;
  editorRef.value.setHtml(html);
  console.log(editorRef.value.getHtml());
};

const sucaiRef = ref<InstanceType<typeof SucaiPopup> | null>();

// 富文本 DOM 元素
const editorRef = shallowRef();

// 素材库过滤器
const filter = ref("");

// 实列化编辑器
const handleCreated = (editor: any) => {
  editorRef.value = editor;
};

// 文本基本信息
interface BaseInfo {
  title: string;
  author?: string;
  cont: string;
}

// 接收父组件参数，并设置默认值
interface RichEditorProps {
  // value: string; // 富文本值 ==> 必传
  baseInfo?: BaseInfo;
  toolbarConfig?: Partial<IToolbarConfig>; // 工具栏配置 ==> 非必传（默认为空）
  editorConfig?: Partial<IEditorConfig>; // 编辑器配置 ==> 非必传（默认为空）
  minHeight?: string; // 富文本高度 ==> 非必传（默认为 500px）
  mode?: "default" | "simple"; // 富文本模式 ==> 非必传（默认为 default）
  hideToolBar?: boolean; // 是否隐藏工具栏 ==> 非必传（默认为false）
  disabled?: boolean; // 是否禁用编辑器 ==> 非必传（默认为false）
  hasAuthor: boolean;
  isShowCard: boolean; //是否展示楼盘卡片
  isSubmit: boolean; //是否显示提交按钮
}
const props = withDefaults(defineProps<RichEditorProps>(), {
  toolbarConfig: () => {
    return {
      excludeKeys: ["group-video", "code", "codeBlock", "group-image"]
      // toolbarKeys: ["undo", "redo", "|", "clearStyle", "|", "fontSize", "bold", "italic", "underline"]
    };
  },
  editorConfig: () => {
    return {
      placeholder: "从这里开始写正文",
      MENU_CONF: {},
      autoFocus: true,
      withCredentials: true
    };
  },
  minHeight: "900px",
  mode: "default",
  hideToolBar: false,
  disabled: false,
  baseInfo: () => {
    return { title: "", author: "", cont: "" };
  },
  hasAuthor: true,
  isShowCard: true,
  isSubmit: false
});

// 获取 el-form 组件上下文
const formContext = inject(formContextKey, void 0);
// 获取 el-form-item 组件上下文
const formItemContext = inject(formItemContextKey, void 0);
// 判断是否禁用上传和删除
const self_disabled = computed(() => {
  return props.disabled || formContext?.disabled;
});

// 判断当前富文本编辑器是否禁用
if (self_disabled.value) nextTick(() => editorRef.value.disable());

// 富文本的内容监听，触发父组件改变，实现双向数据绑定
type EmitProps = {
  (e: "update:value", val: string): void;
  (e: "check-validate"): void;
  (e: "submit", val: any): void;
};
const emit = defineEmits<EmitProps>();
const valueHtml = computed({
  get() {
    return props.baseInfo.cont;
  },
  set(val: string) {
    // 防止富文本内容为空时，校验失败
    if (editorRef.value.isEmpty()) val = "";
    emit("update:value", val);
  }
});

// 自定义插入图片和视频
const customBrowseAndUpload = (type: "video" | "image") => {
  filter.value = type;
  sucaiRef.value?.change();
};

// 编辑框失去焦点时触发
const handleBlur = () => {
  formItemContext?.prop && formContext?.validateField([formItemContext.prop as string]);
};

// 组件销毁时，也及时销毁编辑器
onBeforeUnmount(() => {
  if (!editorRef.value) return;
  editorRef.value.destroy();
});

// ----获取素材库的东西
const getUrl = (val: any) => {
  const base: any = {
    type: filter.value,
    src: val[0].origin_name
  };
  if (val) {
    editorRef.value.focus(); //移动光标
    if (filter.value === "image") {
      editorRef.value.insertNode({
        ...base,
        children: [{ text: "" }]
      });
    } else if (filter.value === "video") {
      editorRef.value.insertNode({
        ...base,
        poster: val[0].cover,
        width: "620",
        children: [{ text: "" }]
      });
    }
  }
};

// const baseInfo = reactive({ title: "", author: "", cont: "" });

const getEditor = () => {
  if (props.baseInfo.title.length > 64 || props.baseInfo.title.length < 1) {
    ElMessage.error("标题字数在1-64个字之间");
    return;
  }
  if (props.hasAuthor) {
    if (props.baseInfo.author!.length > 8 || props.baseInfo.author!.length < 1) {
      ElMessage.error("作者字数在1-8个字之间");
      return;
    }
  }

  if (editorRef.value.isEmpty()) {
    ElMessage.error("请先输入一段正文再提交");
    return;
  }
  props.baseInfo.cont = modifyVideoWidth(editorRef.value.getHtml());

  return props.baseInfo;
};

// 修改video样式
const modifyVideoWidth = (htmlStr: string) => {
  // 匹配所有video标签的width属性
  const reg = /(<video[^>]*?)\s+width=(['"])(.*?)\2/gi;

  // 将匹配到的所有width属性替换为style属性
  const result = htmlStr.replace(reg, '$1 style="width:100%;"');

  // 返回修改后的HTML字符串
  return result;
};

const submit = () => {
  emit("submit", getEditor());
};

defineExpose({
  getEditor
});
</script>

<style scoped lang="scss">
@import "./index.scss";
</style>
